package com.xinqi.modules.prepare.prepare.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.xinqi.common.base.error.CommonErrors;
import com.xinqi.common.base.response.PageInfo;
import com.xinqi.common.base.response.Param;
import com.xinqi.common.mybatis.utils.Pages;
import com.xinqi.common.security.utils.UserHelp;
import com.xinqi.modules.prepare.common.enums.PrepareLimitEnum;
import com.xinqi.modules.prepare.common.manager.PrepareCommonManager;
import com.xinqi.modules.prepare.common.service.PrepareAuthService;
import com.xinqi.modules.prepare.prepare.convert.PrepareMemberConvert;
import com.xinqi.modules.prepare.prepare.domain.PrepareMemberEntity;
import com.xinqi.modules.prepare.prepare.dto.req.PrepareMemberBatchCreateDTO;
import com.xinqi.modules.prepare.prepare.dto.req.PrepareMemberCreateDTO;
import com.xinqi.modules.prepare.prepare.dto.req.PrepareMemberDeleteDTO;
import com.xinqi.modules.prepare.prepare.dto.req.PrepareMemberQueryDTO;
import com.xinqi.modules.prepare.prepare.dto.req.PrepareMemberUpdateDTO;
import com.xinqi.modules.prepare.prepare.dto.rsp.PrepareMemberResultDTO;
import com.xinqi.modules.prepare.prepare.enums.PrepareMemberPermissionEnum;
import com.xinqi.modules.prepare.prepare.enums.PrepareMemberRoleEnum;
import com.xinqi.modules.prepare.prepare.enums.PrepareOperateLogEnum;
import com.xinqi.modules.prepare.prepare.enums.PrepareOperateTypeEnum;
import com.xinqi.modules.prepare.prepare.enums.PrepareSubOperateTypeEnum;
import com.xinqi.modules.prepare.prepare.manager.PrepareMemberManager;
import com.xinqi.modules.prepare.prepare.manager.PrepareOperateLogManager;
import com.xinqi.modules.prepare.prepare.service.PrepareMemberService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.xinqi.common.base.error.CommonErrors.BAD_REQUEST;

/**
 * 备课区成员服务层实现
 *
 * @author: system
 * @date: 2023/03/19
 */
@Validated
@Service("prepareMemberService")
@RequiredArgsConstructor
public class PrepareMemberServiceImpl implements PrepareMemberService {
    private final PrepareAuthService prepareAuthService;
    private final PrepareMemberConvert prepareMemberConvert;
    private final PrepareMemberManager prepareMemberManager;
    private final PrepareCommonManager prepareCommonManager;
    private final PrepareOperateLogManager prepareOperateLogManager;
//    @Lazy
//    private final ChatRemindSyncServiceImpl chatRemindSyncService;

    /**
     * 分页查询 备课区成员数据
     */
    @Override
    @DS("slaver")
    public PageInfo<PrepareMemberResultDTO> page(Param pageable, PrepareMemberQueryDTO query) {
        IPage<PrepareMemberResultDTO> page = prepareMemberManager.findPage(
            Pages.page(pageable, OrderItem.desc("a.id")),
            query);
        return Pages.convert(page);
    }

    /**
     * 查询 备课区成员数据
     */
    @Override
    public List<PrepareMemberResultDTO> find(PrepareMemberQueryDTO query) {
        return prepareMemberManager.findList(query);
    }

    /**
     * 根据id查询 备课区成员数据
     */
    @Override
    public PrepareMemberResultDTO findById(Long id) {
        BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        PrepareMemberQueryDTO query = new PrepareMemberQueryDTO();
        query.setId(id);
        List<PrepareMemberResultDTO> list = find(query);
        return CollectionUtils.isNotEmpty(list) ? list.get(0) : null;
    }

    /**
     * 新增 备课区成员数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long insert(@Valid PrepareMemberCreateDTO dto) {
        // 校验当前用户权限
        Long prepareId = dto.getPrepareId();
        prepareAuthService.check(prepareId, UserHelp.userId(), PrepareMemberPermissionEnum.添加成员协同备课区);
        // 备课区人数上限
        checkPrepareJoinLimit(dto.getPrepareId(), 1);
        return insertMember(dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertBatch(@Valid PrepareMemberBatchCreateDTO dto) {
        Long prepareId = dto.getPrepareId();
        List<Long> userIdList = dto.getUserIdList();
        // 校验当前用户权限
        prepareAuthService.check(prepareId, UserHelp.userId(), PrepareMemberPermissionEnum.添加成员协同备课区);
        // 备课区人数上限
        checkPrepareJoinLimit(dto.getPrepareId(), userIdList.size());
        // 循环添加成员
        userIdList.forEach(userId -> {
            PrepareMemberCreateDTO createDTO = new PrepareMemberCreateDTO();
            createDTO.setPrepareId(prepareId);
            createDTO.setUserId(userId);
            insertMember(createDTO);
        });
        return true;
    }

    private Long insertMember(PrepareMemberCreateDTO dto) {
        Long prepareId = dto.getPrepareId();
        Long userId = dto.getUserId();
        BAD_REQUEST.check(prepareCommonManager.existsUser(userId), "用户不存在");
        // 备课区用户加入数量上限
        checkUserJoinLimit(userId, 1);
        // 查询当前用户是否存在
        PrepareMemberEntity member = prepareMemberManager.findByPrepareIdAndUserId(prepareId, dto.getUserId());
        if (member != null) {
            return member.getId();
        }
        PrepareMemberEntity entity = prepareMemberConvert.create(dto);
        // 默认为成员
        entity.setRole(PrepareMemberRoleEnum.MEMBER);
        // 加入时间
        entity.setJoinTime(LocalDateTime.now());
        prepareMemberManager.save(entity);
        // 添加日志
        prepareOperateLogManager.addMemberOperateLog(
            entity,
            PrepareOperateTypeEnum.MEMBER_CHANGE,
            PrepareSubOperateTypeEnum.ADD, null, null);

        //新奇提醒机器人 -- 被邀请加入备课区
//        chatRemindSyncService.joinPrepare(LoginHelper.getNickname(), prepareId, userId);

        return entity.getId();
    }

    private void checkPrepareJoinLimit(Long prepareId, int num) {
        long count = prepareMemberManager.countByPrepareId(prepareId, PrepareMemberRoleEnum.MEMBER);
        PrepareLimitEnum.协同备课成员数量上限.check(count + num);
    }

    private void checkUserJoinLimit(Long userId, int num) {
        long count = prepareMemberManager.countByUserId(userId, PrepareMemberRoleEnum.MEMBER);
        PrepareLimitEnum.用户加入备课区数量上限.check(count + num);
    }

    /**
     * 根据id修改 备课区成员数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateById(@Valid PrepareMemberUpdateDTO dto) {
        Long currentUserId = UserHelp.userId();
        BAD_REQUEST.check(!Objects.equals(dto.getRole(), PrepareMemberRoleEnum.LEADER), "不能变更为组长");
        // 校验当前用户权限
        prepareAuthService.check(dto.getPrepareId(), currentUserId, PrepareMemberPermissionEnum.添加成员协同备课区);
        PrepareMemberEntity old = Optional.ofNullable(prepareMemberManager.getById(dto.getId()))
            .orElseThrow(() -> BAD_REQUEST.asException("数据不存在"));
        BAD_REQUEST.check(Objects.equals(old.getPrepareId(), dto.getPrepareId()), "备课区不一致");
        PrepareMemberEntity entity = prepareMemberConvert.update(dto);
        // 添加日志
        prepareOperateLogManager.addMemberOperateLog(
            entity,
            PrepareOperateTypeEnum.MEMBER_CHANGE,
            PrepareSubOperateTypeEnum.CHANGE, null, null);
        return prepareMemberManager.updateById(entity);
    }

    /**
     * 根据id删除 备课区成员数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Long id) {
        Long currentUserId = UserHelp.userId();
        BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        PrepareMemberEntity entity = Optional.ofNullable(prepareMemberManager.getById(id))
            .orElseThrow(() -> BAD_REQUEST.asException("数据不存在"));
        BAD_REQUEST.check(!Objects.equals(entity.getRole(), PrepareMemberRoleEnum.LEADER), "不能删除组长");
        // 校验当前用户权限
        prepareAuthService.check(entity.getPrepareId(), currentUserId, PrepareMemberPermissionEnum.添加成员协同备课区);
        // 添加日志
        prepareOperateLogManager.addMemberOperateLog(
            entity,
            PrepareOperateTypeEnum.MEMBER_CHANGE,
            PrepareSubOperateTypeEnum.REMOVE, null, null);
        boolean flag = prepareMemberManager.removeById(id);

        if (flag) {
            //新奇提醒机器人 -- 你被移出备课区通知
//            chatRemindSyncService.dropPrepare(LoginHelper.getNickname(), entity.getPrepareId(), entity.getUserId());
        }
        return flag;
    }

    /**
     * 根据id删除 备课区成员数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(PrepareMemberDeleteDTO dto) {
        return deleteById(dto.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteByIds(Long prepareId, List<Long> ids) {
        BAD_REQUEST.check(CollectionUtils.isNotEmpty(ids), "成员ID列表不能为空");
        Long currentUserId = UserHelp.userId();
        prepareAuthService.check(prepareId, currentUserId, PrepareMemberPermissionEnum.添加成员协同备课区);
        List<PrepareMemberEntity> list = prepareMemberManager.listByIds(ids);
        if (CollectionUtils.isEmpty(list)) {
            throw BAD_REQUEST.asException("未找到对应列表");
        }
        list.stream()
            .filter(v -> !Objects.equals(v.getRole(), PrepareMemberRoleEnum.LEADER))
            .forEach(v ->
                prepareOperateLogManager.addMemberOperateLog(
                    v, PrepareOperateTypeEnum.MEMBER_CHANGE, PrepareSubOperateTypeEnum.REMOVE, null, null)
            );
        boolean flag = prepareMemberManager.deleteByIds(prepareId, ids);

        if (flag) {
            //新奇提醒机器人 -- 你被移出备课区通知
            List<Long> userIds = list.stream().map(PrepareMemberEntity::getUserId).collect(Collectors.toList());
//            chatRemindSyncService.batchDropPrepare(LoginHelper.getNickname(), prepareId, userIds);
        }
        return flag;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean quit(Long prepareId, Long userId) {
        // 获取成员信息
        PrepareMemberEntity entity = Optional.ofNullable(prepareMemberManager.findByPrepareIdAndUserId(prepareId, userId))
            .orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("成员不存在"));
        PrepareMemberResultDTO memberResult = Optional.ofNullable(findById(entity.getId()))
            .orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("成员不存在"));
        BAD_REQUEST.check(!Objects.equals(entity.getRole(), PrepareMemberRoleEnum.LEADER), "组长不能退出");
        // 添加日志
        prepareOperateLogManager.addMemberOperateLog(entity, PrepareOperateLogEnum.MEMBER_QUIT, null, null);

        boolean flag = prepareMemberManager.deleteById(entity.getId());
        if (flag) {
            //新奇提醒机器人 -- 退出备课区通知
//            chatRemindSyncService.quitPrepare(memberResult.getNickname(), prepareId);
        }

        return flag;
    }

}
